package com.hucsmn.chatroom;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.SocketException;
import java.util.Scanner;

/**
 * 作业题五：
 * 使用基于 tcp 协议的编程模型实现多人同时在线聊天和传输文件，
 * 要求每个客户端将发送的聊天内容和文件发送到服务器，服务器接收到后转发给当前所有在线的客户端。
 */
public class ChatClientTest {
    public static void main(String[] args) {
        // 建立客户端对象。
        ChatClient client = new ChatClient();
        System.out.println("聊天客户端");
        System.out.println("服务器地址: " + client.getAddress() + ":" + client.getPort());
        System.out.println();

        // 获取昵称。
        Scanner sc = new Scanner(System.in);
        String nick = null;
        while (true) {
            System.out.print("请输入聊天室昵称: ");
            nick = sc.nextLine().trim();
            if (!nick.isEmpty()) {
                break;
            }
            System.out.println("输入错误: 昵称不能为空！");
        }
        client.setNick(nick);

        // 开始聊天。
        try (ChatClient.MessageChannel chat = client.chat()) {
            // 后台接收聊天消息。
            Thread echo = new Thread(() -> echo(chat), "echo");
            echo.setDaemon(true);
            echo.start();

            while (true) {
                String input = sc.nextLine().trim();
                if (input.isEmpty()) {
                    continue;
                }

                // 发送消息。
                if (!input.startsWith("/")) {
                    chat.say(input);
                    continue;
                }

                // 执行命令。
                String[] cmd = input.split("\\s+");
                if (command(client, cmd)) {
                    break;
                }
            }
        } catch (IOException e) {
            System.err.println("错误: " + e);
        }
    }

    /**
     * 后台消息接收。
     *
     * @param chat 聊天室连接。
     */
    private static void echo(ChatClient.MessageChannel chat) {
        try {
            String message;
            while ((message = chat.listen()) != null) {
                System.out.println(message);
            }
        } catch (SocketException e) {
            // 主线程关闭 Socket 导致 listen 读取异常，不应该报错。
        } catch (IOException e) {
            System.err.println("消息读取错误: " + e);
        }
    }

    /**
     * 处理命令行。
     *
     * @param client 客户端信息。
     * @param cmd 命令行参数。
     * @return 是否退出客户端。
     */
    private static boolean command(ChatClient client, String... cmd) {
        if (cmd.length == 0) {
            return false;
        }

        switch (cmd[0].toLowerCase()) {
            case "/s":
            case "/send":
                send(client, cmd);
                break;
            case "/r":
            case "/recv":
            case "/receive":
                receive(client, cmd);
                break;
            case "/q":
            case "/quit":
            case "/exit":
                return true;
            case "/?":
            case "/h":
            case "/help":
                System.err.println("  命令列表:");
                System.err.println("    /send <file>");
                System.err.println("    /receive <name> <dir>");
                System.err.println("    /quit");
                System.err.println("    /help");
                System.err.println();
                break;
            default:
                System.err.println("错误的命令：" + String.join(" ", cmd));
        }
        return false;
    }

    /**
     * 后台发送文件。
     *
     * @param client 客户端信息。
     * @param cmd 命令行参数。
     */
    private static void send(ChatClient client, String[] cmd) {
        if (cmd.length != 2) {
            System.err.println("命令错误: 需要提供要发送的文件路径！");
            return;
        }

        File file = new File(cmd[1]);
        System.err.println("后台任务: 开始发送文件 '" + file.getName() + "'...");
        new Thread(() -> {
            try {
                client.send(file);
                System.err.println("后台任务: 文件 '" + file.getName() + "' 发送成功！");
            } catch (IOException e) {
                System.err.println("后台任务: 文件 '" + file.getName() + "' 发送失败: " + e);
            }
        }, "send-" + file.getName()).start();
    }

    /**
     * 后台接收文件。
     *
     * @param client 客户端信息。
     * @param cmd 命令行参数。
     */
    private static void receive(ChatClient client, String[] cmd) {
        if (cmd.length != 3) {
            System.err.println("命令错误: 需要提供要接收的文件名，以及接收文件夹！");
            return;
        }

        File dir = new File(cmd[2]);
        if (dir.isFile()) {
            System.err.println("命令错误: 接收文件夹无效！");
            return;
        }
        dir.mkdirs();

        String name = cmd[1];
        File file = new File(dir, name);
        System.err.println("后台任务: 开始接收文件 '" + name + "'...");
        new Thread(() -> {
            try {
                client.receive(name, file);
                System.err.println("后台任务: 文件 '" + name + "' 接收成功！");
            } catch (FileNotFoundException e) {
                System.err.println("后台任务: 文件 '" + name + "' 不存在！");
            } catch (IOException e) {
                System.err.println("后台任务: 文件 '" + file.getName() + "' 接收失败: " + e);
            }
        }, "receive-" + name).start();
    }
}
